﻿#include <sstream>
#include <iomanip>//通常用于操纵输出流（std::ostream）和输入流（std::istream）
#include <iostream>
#include "UI.h"
#include "Manager.h"

UI::UI() {
    title = "系统名";
    width = 50;
    manager = Manager::getInstance();// 获取了 Manager 类的单例实例，并将其赋值给 manager 成员变量
}

std::string UI::makeOptionsName(const int &index, const std::string &option) {
    std::stringstream ss;
    ss << "[" << index << "] " << option;
    return ss.str();
}

void UI::showLineStar() {
    std::cout << std::setfill('*') << std::setw(width) << "*" << std::endl;
}

// 添加选项
void UI::addOption(const std::string &options) {
    this->options.push_back(options);//push_back 是向动态数组（向量）的末尾添加新元素的方法
}

// 设置标题
void UI::setTitle(const std::string &title) {
    this->title = title;
}

// 显示界面
void UI::showUI(bool isClear) {
    if (isClear) {
        system("cls");
    }

    //	显示标题
    {
        showLineStar();
        std::cout << title << std::endl;
        showLineStar();
        std::cout << std::endl;
    }

    for (int i = 0; i < options.size(); i++) {
        std::cout << makeOptionsName(i + 1, options[i]) << std::endl;
        //使用循环遍历 options 向量，调用 makeOptionsName 函数为每个选项生成带有索引的字符串，然后输出
    }
    showLineStar();
    std::cout << "请选择 (" << 1 << "-" << options.size() << "): ";//options.size() 获取选项的数量，用于提示用户可以选择的范围
}

// 运行界面
void UI::run() {
    showUI();// 显示初始用户界面
    int index;// 用于存储用户输入的选项索引
    while (std::cin >> index) {// 循环接受用户输入
        if (index >= 1 && index <= options.size()) {// 判断输入是否在有效范围内
            bool isContinue = call(index);// 调用用户选择的操作
            if (!isContinue) {// 如果返回 false，退出循环
                break;
            }
            showUI();// 显示更新后的用户界面
        } else {
            std::cout << "输入错误，请重新输入：";// 输入不在有效范围内，提示用户重新输入
        }
    }
}

// 任务执行完成后的提示
void UI::backTip() {
    std::cout << "任务执行完成，按任意键继续..." << std::endl;
    std::cin.get();// 等待用户按下回车键
    std::cin.get();// 再次等待用户按下回车键（以防止上一次的回车键输入被用作下一次输入）
    system("cls");// 清空控制台屏幕
}

// 调用任务
bool UI::call(int index) {
    if (index == options.size()) {//如果用户选择的索引等于 options.size()，也就是最后一个选项的索引，函数返回 false。这通常被解释为用户选择了退出或返回上一级菜单。
        return false;
    }
    return true;
}


mainUI::mainUI() {
    manager = Manager::getInstance();
    manager->initData();
    setTitle("*                  图书管理系统                  *");
    addOption("系统维护");
    addOption("查找书籍");
    addOption("借还书籍");
    addOption("显示所有书籍");
    addOption("保存并退出");
}

//根据传入的参数 index 执行不同的操作，创建不同的 UI 对象并调用其 run 方法
bool mainUI::call(int index) {
    switch (index) {
        case 1:
            (new maintenanceUI())->run();
            break;
        case 2:
            (new searchUI())->run();
            break;
        case 3:
            (new borrowAndReturnUI())->run();
            backTip();
            break;
        case 4:
            (new displayUI())->run();
            break;
        case 5:
            manager->Exit();
            return false;
    }
    return true;
}

maintenanceUI::maintenanceUI() {
    manager = Manager::getInstance();
    setTitle("*                    系统维护                    *");
    addOption("添加书籍");
    addOption("删除书籍");
    addOption("修改书籍");
    addOption("查看借阅记录");
    addOption("返回");
}

bool maintenanceUI::call(int index) {
    switch (index) {
        case 1:
            (new addBookUI())->run();
            break;
        case 2:
            manager->deleteBook();
            backTip();
            break;
        case 3:
            manager->modifyBook();
            backTip();
            break;
        case 4:
            (new showRecordUI())->run();
            break;
        case 5:
            return false;
    }
    return true;
}

addBookUI::addBookUI() {
    manager = Manager::getInstance();
    setTitle("*                    添加书籍                    *");
    addOption("添加单本书籍");
    addOption("批量添加书籍");
    addOption("返回");
}

bool addBookUI::call(int index) {
    switch (index) {
        case 1:
            manager->addBookSingle();
            backTip();
            break;
        case 2:
            manager->addBookBatch();
            backTip();
            break;
        case 3:
            return false;
    }
    return true;
}

showRecordUI::showRecordUI() {
    manager = Manager::getInstance();
    setTitle("*                  查看借阅记录                  *");
    addOption("显示所有记录");
    addOption("显示逾期记录");
    addOption("显示未归还记录");
    addOption("显示已归还记录");
    addOption("显示续借记录");
    addOption("返回");
}

bool showRecordUI::call(int index) {
    switch (index) {
        case 1:
            manager->displayBorrowingRecords();
            backTip();
            break;
        case 2:
            manager->displayBorrowingRecords("逾期");
            backTip();
            break;
        case 3:
            manager->displayBorrowingRecords("借阅中", "今日到期");
            backTip();
            break;
        case 4:
            manager->displayBorrowingRecords("已归还");
            backTip();
            break;
        case 5:
            manager->displayBorrowingRecords("续借中");
            backTip();
            break;
        case 6:
            return false;
    }
    return true;
}

searchUI::searchUI() {
    manager = Manager::getInstance();
    setTitle("*                    查找书籍                    *");
    addOption("按书名查找");
    addOption("按作者查找");
    addOption("按 ISBN 号查找");
    addOption("按出版社查找");
    addOption("按条码号查找");
    addOption("按分类号查找");
    addOption("按馆藏地查找");
    addOption("返回");
}

bool searchUI::call(int index) {
    switch (index) {
        case 1:
            manager->searchBookByName();
            backTip();
            break;
        case 2:
            manager->searchBookByAuthor();
            backTip();
            break;
        case 3:
            manager->searchBookByISBN();
            backTip();
            break;
        case 4:
            manager->searchBookByPublisher();
            backTip();
            break;
        case 5:
            manager->searchBookByBarcode();
            backTip();
            break;
        case 6:
            manager->searchBookByClassification();
            backTip();
            break;
        case 7:
            manager->searchBookByLocation();
            backTip();
            break;
        case 8:
            return false;
    }
    return true;
}

borrowAndReturnUI::borrowAndReturnUI() {
    manager = Manager::getInstance();
    setTitle("*                    借还书籍                    *");
    addOption("借阅书籍");
    addOption("归还书籍");
    addOption("续借书籍");
    addOption("返回");
}

void borrowAndReturnUI::showUI(bool isClear) {
    // 输入借阅人
    std::cout << "请输入借阅 ID：";
    std::cin >> borrowerID;

    if (isClear) {
        system("cls");
    }
    //	显示标题
    {
        showLineStar();
        std::cout << '*';
        std::cout << std::setfill(' ') << std::setw((width - 1 - title.length()) / 2 + title.length()) << title;
        std::cout << std::setfill(' ') << std::setw(width - (width - title.length()) / 2 - title.length()) << '*'
                  << std::endl;
        showLineStar();
        std::cout << "当前操作人：" << borrowerID << std::endl;
        std::cout << std::endl;
    }
    for (int i = 0; i < options.size(); i++) {
        std::cout << makeOptionsName(i + 1, options[i]) << std::endl;
    }
    showLineStar();
    std::cout << "请选择 (" << 1 << "-" << options.size() << "): ";
}

bool borrowAndReturnUI::call(int index) {
    switch (index) {
        case 1:
            manager->borrowBook(borrowerID);
            backTip();
            break;
        case 2:
            manager->returnBook(borrowerID);
            backTip();
            break;
        case 3:
            manager->renewBook(borrowerID);
            backTip();
            break;
        case 4:
            return false;
    }
    return true;
}

displayUI::displayUI() {
    manager = Manager::getInstance();
    setTitle("*                  显示所有书籍                  *");
    addOption("默认排序");
    addOption("按书名排序");
    addOption("按作者排序");
    addOption("按 ISBN 号排序");
    addOption("按出版社排序");
    addOption("按条码号排序");
    addOption("按分类号排序");
    addOption("返回");
}

bool displayUI::call(int index) {
    switch (index) {
        case 1:
            manager->displayBook();
            backTip();
            break;
        case 2:
            manager->displayBookByName();
            backTip();
            break;
        case 3:
            manager->displayBookByAuthor();
            backTip();
            break;
        case 4:
            manager->displayBookByISBN();
            backTip();
            break;
        case 5:
            manager->displayBookByPublisher();
            backTip();
            break;
        case 6:
            manager->displayBookByBarcode();
            backTip();
            break;
        case 7:
            manager->displayBookByClassification();
            backTip();
            break;
        case 8:
            return false;
    }
    return true;
}
